home *** CD-ROM | disk | FTP | other *** search
Wrap
/* File: CompositeClassDriver.c Contains: Core functionality to Composite Class Driver Version: xxx put version here xxx Copyright: © 1997-1999 by Apple Computer, Inc., all rights reserved. */ #include <Types.h> #include <Devices.h> #include <processes.h> #include <DriverServices.h> #include <USB.h> #include "CompositeClassDriver.h" extern usbCompositePBStruct myCompositePBRecord; void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock) { paramblock->usbReference = theDeviceRef; paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; paramblock->pbLength = sizeof(usbCompositePBStruct); paramblock->pbVersion = kUSBCurrentPBVersion; paramblock->usb.cntl.WIndex = 0; paramblock->usbBuffer = nil; paramblock->usbStatus = kUSBNoErr; paramblock->usbReqCount = 0; paramblock->usbActCount = 0; paramblock->usb.cntl.WValue = 0; paramblock->usbFlags = 0; } Boolean immediateError(OSStatus err) { return((err != kUSBPending) && (err != kUSBNoErr) ); } void CompositeDeviceInitiateTransaction(USBPB *pb) { register usbCompositePBStruct *pCompositePB; OSStatus myErr; pCompositePB = (usbCompositePBStruct *)(pb); if (pCompositePB->expertTerminatePending) // TCC <USB16> return; pCompositePB->transDepth++; if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Illegal Transaction Depth", pCompositePB->pb.usbRefcon); } if (pCompositePB->driverRemovalPending) { pCompositePB->pb.usbRefcon = kReturnFromDriver; return; } switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction) { case kGetFullConfiguration0: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); pCompositePB->pb.usb.cntl.WIndex = 0; pCompositePB->pb.usbRefcon |= kCompletionPending; pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; myErr = USBGetFullConfigurationDescriptor(pb); if(immediateError(myErr)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetFullConfiguration (#1) - immediate error", myErr); } break; case kSetConfig: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); pCompositePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice); pCompositePB->pb.usb.cntl.BRequest = kUSBRqSetConfig; pCompositePB->pb.usb.cntl.WValue = pCompositePB->pFullConfigDescriptor->configValue; /* Use configuration ID value from descriptor */ pCompositePB->pb.usbRefcon |= kCompletionPending; pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; myErr = USBDeviceRequest(pb); if(immediateError(myErr)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kSetConfig - immediate error", myErr); } break; case kNewInterfaceRef: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); // Note: pCompositePB->usb.cntl.WIndex will be set to zero by InitParamBlock // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef pCompositePB->pb.usb.cntl.WIndex = pCompositePB->interfaceIndex; pCompositePB->pb.usbRefcon |= kCompletionPending; pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; myErr = USBNewInterfaceRef(pb); if(immediateError(myErr)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kNewInterfaceRef - immediate error", myErr); } break; default: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon); pCompositePB->pb.usbRefcon = kUndefined + kReturnFromDriver; break; } // At this point the control is returned to the system. If a USB transaction // has been initiated, then it will call the Complete procs // (below) to handle the results of the transaction. } void CompositeDeviceCompletionProc(USBPB *pb) { OSStatus myErr; register usbCompositePBStruct *pCompositePB; USBInterfaceDescriptorPtr pInterfaceDescriptor; UInt32 i; pCompositePB = (usbCompositePBStruct *)(pb); if (pCompositePB->expertTerminatePending) // TCC <USB16> return; pCompositePB->transDepth--; if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Illegal Transaction Depth", pCompositePB->transDepth); } if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending)) { USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": Completion Error", pCompositePB->pb.usbStatus); pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver); pCompositePB->pb.usbRefcon |= kRetryTransaction; pCompositePB->retryCount--; if (!pCompositePB->retryCount) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Too many retries", pCompositePB->pb.usbRefcon); pCompositePB->pb.usbRefcon = kReturnFromDriver; return; } } else { pCompositePB->pb.usbRefcon &= ~kRetryTransaction; pCompositePB->retryCount = kCompositeRetryCount; } if (pCompositePB->pb.usbRefcon & kCompletionPending) { pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver); switch(pCompositePB->pb.usbRefcon) { case kGetFullConfiguration0: pCompositePB->pFullConfigDescriptor = pCompositePB->pb.usbBuffer; if (pCompositePB->pFullConfigDescriptor == nil) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetFullConfiguration - pointer is nil", pCompositePB->pb.usbRefcon); pCompositePB->pb.usbRefcon = kReturnFromDriver; break; } BlockCopy( (void *)pCompositePB->pFullConfigDescriptor, (void *)(&(pCompositePB->partialConfigDescriptor)), (Size)(sizeof(USBConfigurationDescriptor) ) ); USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName" - Configuration->maxPower = ", pCompositePB->pFullConfigDescriptor->maxPower); USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName" - Hub supplied power = ", pCompositePB->busPowerAvailable); if (pCompositePB->pFullConfigDescriptor->maxPower <= pCompositePB->busPowerAvailable) { pCompositePB->pb.usbRefcon = kSetConfig; } else { USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, pCompositePB->pFullConfigDescriptor->maxPower); USBExpertFatalError(pCompositePB->pb.usbReference, kUSBDevicePowerProblem, kCompositeDriverName" - Insufficient power for device", pCompositePB->busPowerAvailable); pCompositePB->pb.usbRefcon = kReturnFromDriver; } break; case kSetConfig: /* get all the interface descriptors and save them */ for (i=0; i < pCompositePB->partialConfigDescriptor.numInterfaces; i++) { pCompositePB->interfaceRefArray[i] = 0; myErr = GetInterfaceDescriptor(pCompositePB->pFullConfigDescriptor, (UInt32)i, &pInterfaceDescriptor); if (kUSBNoErr == myErr) { BlockCopy((void *)pInterfaceDescriptor, (void *)(&(pCompositePB->interfaceDescriptors[i])), (Size)(pInterfaceDescriptor->length)); } else /* if GetInterfaceDescriptor returned an error, then set the length to zero (so we know later) */ { pCompositePB->interfaceDescriptors[i].length = 0; } } pCompositePB->interfaceIndex = 0; pCompositePB->interfaceCount = pCompositePB->partialConfigDescriptor.numInterfaces; pCompositePB->pb.usbRefcon = kNewInterfaceRef; break; case kNewInterfaceRef: /* save the new interface ref for this interface */ pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex] = pCompositePB->pb.usbReference; /* only install the interface driver if we had a valid interface descriptor */ if (pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex].length != 0) { USBExpertInstallInterfaceDriver(pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex], &pCompositePB->deviceDescriptor, &pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex], pCompositePB->deviceRef, 0); } /* advance to the next interface */ pCompositePB->interfaceIndex++; /* if there's more interfaces, then just keep cycling through kNewInterfaceRef */ if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount) { pCompositePB->pb.usbRefcon = kNewInterfaceRef; } else { pCompositePB->pb.usbRefcon = kReturnFromDriver; } break; default: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon); pCompositePB->pb.usbRefcon = kReturnFromDriver; break; } } if (!(pCompositePB->pb.usbRefcon & kReturnFromDriver) && (!pCompositePB->driverRemovalPending)) CompositeDeviceInitiateTransaction(pb); }